﻿using UnityEngine;
using System.Collections;
using System.Xml;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using Tools;

public class ResourceLoad : MonoBehaviour
{

    private string serverUrl = null;
    private string xmlUrl = null;
    private string platForm = null;
    public delegate void ResourceLoadFinished();
    void Awake()
    {
        //http://docs.unity3d.com/Manual/PlatformDependentCompilation.html unity平台预判断
#if UNITY_ANDROID
        Debug.Log("这里是安卓设备");
        platForm = "Android";
#endif

#if UNITY_IPHONE
        Debug.Log("这里是苹果设备");
        platForm = "IOS";
#endif

#if UNITY_STANDALONE_WIN
        Debug.Log("我是从Windows的电脑上运行的");
        platForm = "Windows32";
#endif

#if UNITY_WEBPLAYER
        Debug.Log("我是从WebPlayer上运行的");
        platForm = "WebPlayer";
#endif
    }

    void Start()
    {
        //Invoke("loadLevel", 1f);
        serverUrl = Path.Combine(ServerConfig.ServerConfig.GetServer(), platForm);
        xmlUrl = Path.Combine(serverUrl, "flist.base.xml");

        StartCoroutine(getFileXMLList(xmlUrl, delegate()
        {
            Debug.Log("资源下载成功");//文件保存的路径 C:\Users\ding\AppData\LocalLow\aladdin\ABTest\FlistTemp\
            var newFile = Application.persistentDataPath + "/FlistTemp/flist.base.xml";
            var oldFile = Application.persistentDataPath + "/flist.base.xml";
            //判断本地是否有这个文件，如果没有则下载，并且加载模型，如果有的话则对比
            if (!FileManager.isFileExits(oldFile))
            {
                //读取最新列表，下载对应资源
                LoadResource(newFile, delegate()
                {
                    FileManager.fileCopy(newFile, oldFile);
                    FileManager.deleteFile(newFile);
                    loadLevel();
                });
            }
            else //对比MD5
            {
                if (FileManager.compareTwoFiles(newFile, oldFile)) //相等进入游戏
                {
                    Debug.Log("资源是最新的,可以进入游戏");
                    FileManager.deleteFile(newFile);
                    loadLevel();
                }
                else
                {
                    //进入资源对比
                    Dictionary<string, string> dicDis = compareTwoFilesAndGetDif(newFile, oldFile, Encoding.UTF8);
                    if (dicDis != null)
                    {
                        var difFile = Application.persistentDataPath + "/FlistTemp/diftemp.xml";
                        FileCollection disfc = new FileCollection();
                        FileInfoMation fileinfo = null;
                        List<FileInfoMation> fileinfolist = new List<FileInfoMation>();
                        foreach (KeyValuePair<string, string> pair in dicDis)
                        {
                            fileinfo = new FileInfoMation { Path = pair.Key, Hash = pair.Value };
                            fileinfolist.Add(fileinfo);
                        }
                        disfc.Files = fileinfolist.ToArray(); //差异文件
                        XmlHelper.XmlSerializeToFile(disfc, difFile, Encoding.UTF8);
                        LoadResource(difFile, delegate()
                        {
                            FileCollection oldfc = XmlHelper.XmlDeserializeFromFile<FileCollection>(oldFile, Encoding.UTF8);
                            List<FileInfoMation> fileInfoList = new List<FileInfoMation>();
                            foreach (var item in oldfc.Files.AsList()) //遍历原本的资源文件
                            {
                                if (dicDis.ContainsKey(item.Path))
                                {
                                    if (!dicDis[item.Path].Equals(item.Hash))
                                    {
                                        fileInfoList.Add(new FileInfoMation { Hash = dicDis[item.Path], Path = item.Path });
                                        dicDis.Remove(item.Path);
                                    }
                                }
                                else
                                    fileInfoList.Add(item);
                            }
                            foreach (KeyValuePair<string, string> keypair in dicDis)
                            {
                                fileInfoList.Add(new FileInfoMation { Path = keypair.Key, Hash = keypair.Value });
                            }
                            oldfc.Files = fileInfoList.ToArray();
                            if (FileManager.deleteFile(oldFile))
                            {
                                XmlHelper.XmlSerializeToFile(oldfc, oldFile, Encoding.UTF8);
                                if (Tools.FileManager.deleteDirs(new DirectoryInfo(Application.persistentDataPath + "/FlistTemp")))
                                {
                                    Debug.Log("资源增量更新完毕");
                                    loadLevel();
                                }
                            }
                        });
                    }
                }
            }
        }));

        #region xml序列化和反序列化测试
        //var file1 = new FileInfoMation { Path = "1111.prefab", Hash = "11111111111" };
        //var file2 = new FileInfoMation { Path = "2222.prefab", Hash = "2222" };

        //FileCollection fc = new FileCollection();
        //List<FileInfoMation> files = new List<FileInfoMation>();
        //files.Add(file1);
        //files.Add(file2);
        //fc.Files = files.ToArray();

        ////写入文件到沙盒
        ////xml序列化
        //XmlHelper.XmlSerializeToFile(fc, Application.persistentDataPath + "\\FlistTemp\\test.xml", Encoding.UTF8);
        //string xmlinfo = XmlHelper.XmlSerialize(fc, Encoding.UTF8);
        //Debug.LogError(xmlinfo);

        ////xml反序列化
        //FileCollection c2 = XmlHelper.XmlDeserialize<FileCollection>(xmlinfo, Encoding.UTF8);
        //Debug.LogError(c2.Files[0].Hash);
        //Debug.LogError(c2.Files[0].Path);

        //FileCollection fcnew = XmlHelper.XmlDeserializeFromFile<FileCollection>(Application.persistentDataPath + "\\FlistTemp\\test.xml", Encoding.UTF8);
        //foreach (FileInfoMation fi in fcnew.Files)
        //{
        //    Debug.LogError(fi.Hash);
        //    Debug.LogError(fi.Path);
        //}
        #endregion
    }

    Dictionary<string, string> compareTwoFilesAndGetDif(string newfile, string oldfile, Encoding encoding)
    {
        Dictionary<string, string> dicDisInfo = null;
        if (File.Exists(newfile) && File.Exists(oldfile))
        {
            dicDisInfo = new Dictionary<string, string>();
            FileCollection told = XmlHelper.XmlDeserializeFromFile<FileCollection>(oldfile, encoding);
            FileCollection tnew = XmlHelper.XmlDeserializeFromFile<FileCollection>(newfile, encoding);
            Dictionary<string, string> oldDic = new Dictionary<string, string>();
            Dictionary<string, string> newDic = new Dictionary<string, string>();
            foreach (var item in told.Files.AsList<FileInfoMation>())
            {
                oldDic.Add(item.Path, item.Hash);
            }
            foreach (var item in tnew.Files.AsList<FileInfoMation>())
            {
                newDic.Add(item.Path, item.Hash);
            }

            foreach (KeyValuePair<string, string> newPair in newDic)
            {
                // 旧版本中有,还要对比md5值
                if (oldDic.ContainsKey(newPair.Key))
                {
                    if (oldDic[newPair.Key] != newDic[newPair.Key])
                    {
                        dicDisInfo.Add(newPair.Key, newPair.Value);
                    }
                }
                else
                {
                    dicDisInfo.Add(newPair.Key, newPair.Value);
                }
            }
            if (dicDisInfo.Count <= 0)
                dicDisInfo = null;
        }
        return dicDisInfo;
    }

    void LoadResource(string xmlFile, ResourceLoadFinished callback)
    {
        StartCoroutine(LoadAB(xmlFile, callback));
    }

    IEnumerator LoadAB(string xmlFile, ResourceLoadFinished callback)
    {
        List<FileInfoMation> errorList = new List<FileInfoMation>();
        FileCollection fc = XmlHelper.XmlDeserializeFromFile<FileCollection>(xmlFile, Encoding.UTF8);
        WWW www = null;
        var localPath = Application.persistentDataPath + "/archive";
        foreach (var item in fc.Files.AsList<FileInfoMation>())
        {
            var path = serverUrl + "/" + item.Hash + ".assetbundle";
            www = new WWW(path);
            yield return www;
            if (string.IsNullOrEmpty(www.error))
            {
                if (www.isDone && www.assetBundle != null)
                {
                    byte[] model = www.bytes;
                    int length = model.Length;
                    if (Tools.FileManager.saveOneAssetBundleToLocalFile(localPath, item.Hash + ".assetbundle", model, length, true))
                    {
                        Debug.Log(item.Hash + "写入成功");
                    }
                }
            }
            else
                errorList.Add(item);
        }
        if (errorList.Count > 0)
        {
            Debug.LogError("下载有异常的文件");
            FileCollection fcnew = new FileCollection();
            List<FileInfoMation> files = new List<FileInfoMation>();
            foreach (var fileinfo in errorList)
            {
                var file = new FileInfoMation { Path = fileinfo.Path, Hash = fileinfo.Hash };
                files.Add(file);
                fcnew.Files = files.ToArray();
                XmlHelper.XmlSerializeToFile(fcnew, Application.persistentDataPath + "\\FlistTemp\\ErrorResources.xml", Encoding.UTF8);
            }
        }
        else
                callback();
        yield return null;
    }

    //下载文件
    IEnumerator getFileXMLList(string url, ResourceLoadFinished callback)
    {
        WWW www = new WWW(url);
        yield return www;
        if (www.error != null)
        {
            Debug.LogError(www.error);
        }
        else if (www.isDone)
        {
            byte[] data = www.bytes;
            int length = data.Length;
            if (Tools.FileManager.SaveFile(Path.Combine(Application.persistentDataPath, "FlistTemp"), "flist.base.xml", data, length))
                callback();
        }
    }

    void loadLevel()
    {
        Application.LoadLevel("test");
    }

    void OnGUI()
    {
        GUI.Label(new Rect(Screen.width / 2, Screen.height / 2, 100, 100), "Resources Loading...");
        if (GUI.Button(new Rect(0, 0, 100, 50), "加载"))
        {
            object obj = Object.Instantiate(Resources.Load("prefabs/2DUI")) as GameObject;
        }
    }
}
